using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using ZoneFiveSoftware.Common.Visuals;
using ZoneFiveSoftware.Common.Visuals.Chart;
using FilteredStatistics.Common;
using FilteredStatistics.Controller;
using System.Diagnostics;

namespace FilteredStatistics.Common.Controller
{
    class HeartRatePercentDataTrackProvider : IActivityDataTrackProvider
    {
        public HeartRatePercentDataTrackProvider()
        {
            PluginMain.ZoneCategoryListChanged += new PluginMain.ZoneCategoryChangedEventHandler(OnZoneCategoryChanged);
            m_ActivityDataChangedHelper.PropertyChanged += new PropertyChangedEventHandler(OnActivityDataChanged);
        }

        void OnZoneCategoryChanged(object sender, IZoneCategory category)
        {
            if (DataTrackChanged != null)
            {
                DataTrackChanged(this, new PropertyChangedEventArgs("AxisStripes"));
            }
        }

        void OnActivityDataChanged(object sender, PropertyChangedEventArgs e)
        {
            if (DataTrackChanged != null)
            {
                bool trackNeedsRefresh = false;
                bool axisNeedsRefresh = false;
                bool stripesNeedsRefresh = false;

                if (e.PropertyName == "Activity.HeartRatePerMinuteTrack")
                {
                    trackNeedsRefresh = true;
                }
                else if (e.PropertyName == "Activity.Category")
                {
                    trackNeedsRefresh = true;
                    axisNeedsRefresh = true;
                    stripesNeedsRefresh = true;
                }
                else if (e.PropertyName == "Activity.Duration")
                {
                    trackNeedsRefresh = true;
                }
                else if (e.PropertyName == "ActivityCategory.HeartRateZone")
                {
                    stripesNeedsRefresh = true;
                }
                else if (e.PropertyName == "ActivityCategory.UseParentSettings")
                {
                    stripesNeedsRefresh = true;
                }
                else if (e.PropertyName == "AnalysisSettings.HeartRateSmoothingSeconds")
                {
                    trackNeedsRefresh = true;
                }
                else if (e.PropertyName == "AnalysisSettings.HeartRatePercentType")
                {
                    trackNeedsRefresh = true;
                    axisNeedsRefresh = true;
                    stripesNeedsRefresh = true;
                }

                // Throw events
                if (trackNeedsRefresh)
                {
                    DataTrackChanged(this, new PropertyChangedEventArgs("SmoothedDataTrack"));
                }

                if (axisNeedsRefresh)
                {
                    DataTrackChanged(this, new PropertyChangedEventArgs("Axis"));
                }

                if (stripesNeedsRefresh)
                {
                    DataTrackChanged(this, new PropertyChangedEventArgs("AxisStripes"));
                }
            }
        }

#region IActivityDataTrackProvider Members

        public Guid ReferenceId
        {
            get { return new Guid("b791439f-de38-422c-9d93-d7e73dcc0336"); }
        }

        public bool IsPrimaryDataTrack
        {
            get { return true; }
        }

        public IActivity Activity
        {
            set
            {
                if (m_Activity != value)
                {
                    m_Activity = value;
                    m_ActivityDataChangedHelper.Activity = value;
                }
            }
        }

        public string YAxisLabel
        {
            get
            {
                if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfMax)
                {
                    return CommonResources.Text.LabelHeartRate + " (" + CommonResources.Text.LabelPercentOfMax + ")"; ;
                }
                else if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfReserve)
                {
                    return CommonResources.Text.LabelHeartRate + " (" + CommonResources.Text.LabelPercentOfReserve + ")"; ;
                }

                return CommonResources.Text.LabelHeartRate;
            }
        }

        public string YAxisUnitLabel
        {
            get
            {
                return String.Empty;
            }
        }

        public Color TrackColor
        {
            get { return Color.FromArgb(204, 0, 0); }
        }

        public IAxisFormatter AxisFormatter 
        {
            get
            {
                return new Formatter.Percent();
            }
        }

        public INumericTimeDataSeries SmoothedDataTrack
        {
            get
            {
                if (m_Activity != null)
                {
                    IAthleteInfoEntry lastAthleteEntry = PluginMain.GetApplication().Logbook.Athlete.InfoEntries.LastEntryAsOfDate(m_Activity.StartTime);

                    if (!float.IsNaN(lastAthleteEntry.MaximumHeartRatePerMinute))
                    {
                        INumericTimeDataSeries tempResult = ActivityInfoCache.Instance.GetInfo(m_Activity).SmoothedHeartRateTrack;
                        NumericTimeDataSeries result = new NumericTimeDataSeries();

                        foreach (ITimeValueEntry<float> entry in tempResult)
                        {
                            if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfMax)
                            {
                                double temp = (entry.Value / lastAthleteEntry.MaximumHeartRatePerMinute) * 100;

                                result.Add(tempResult.EntryDateTime(entry), (float)temp);
                            }
                            else if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfReserve &&
                                     !float.IsNaN(lastAthleteEntry.RestingHeartRatePerMinute))
                            {
                                double reserveAmount = lastAthleteEntry.MaximumHeartRatePerMinute - lastAthleteEntry.RestingHeartRatePerMinute;
                                double reserveValue = Math.Max(0, entry.Value - lastAthleteEntry.RestingHeartRatePerMinute);

                                if (reserveAmount > 0)
                                {
                                    double temp = (reserveValue / reserveAmount) * 100;

                                    result.Add(tempResult.EntryDateTime(entry), (float)temp);
                                }
                            }
                        }

                        return result;
                    }

                    return null;
                }

                return null;
            }
        }

        public IList<Guid> DataTrackZoneGuids
        {
            get
            {
                List<Guid> result = new List<Guid>();

                foreach (IZoneCategory category in PluginMain.GetApplication().Logbook.HeartRateZones)
                {
                    result.Add(new Guid(category.ReferenceId));
                }

                return result;
            }
        }

        public Guid DefaultZone
        {
            get
            {
                if (m_Activity != null)
                {
                    return new Guid(m_Activity.Category.HeartRateZone.ReferenceId);
                }
                else
                {
                    return new Guid(PluginMain.GetApplication().Logbook.HeartRateZones[0].ReferenceId);
                }
            }
        }

        public string GetDataTrackZoneName(Guid zoneId)
        {
            foreach (IZoneCategory category in PluginMain.GetApplication().Logbook.HeartRateZones)
            {
                if (category.ReferenceId.Equals(zoneId.ToString()))
                {
                    return category.Name;
                }
            }

            return String.Empty;
        }

        public IList<AxisStripe> GetDataTrackZones(Guid zoneId)
        {
            List<AxisStripe> result = new List<AxisStripe>();
            IAthleteInfoEntry lastAthleteEntry = PluginMain.GetApplication().Logbook.Athlete.InfoEntries.LastEntryAsOfDate(m_Activity.StartTime);

            if (!float.IsNaN(lastAthleteEntry.MaximumHeartRatePerMinute))
            {
                foreach (IZoneCategory category in PluginMain.GetApplication().Logbook.HeartRateZones)
                {
                    if (category.ReferenceId.Equals(zoneId.ToString()))
                    {
                        foreach (INamedLowHighZone zone in category.Zones)
                        {
                            double lower = 0;
                            double upper = 0;

                            if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfMax)
                            {
                                lower = (zone.Low / lastAthleteEntry.MaximumHeartRatePerMinute) * 100;
                                upper = (zone.High / lastAthleteEntry.MaximumHeartRatePerMinute) * 100;
                            }
                            else if (PluginMain.GetApplication().SystemPreferences.AnalysisSettings.HeartRatePercentType == HeartRate.PercentTypes.PercentOfReserve &&
                                     !float.IsNaN(lastAthleteEntry.RestingHeartRatePerMinute))
                            {
                                double reserveAmount = lastAthleteEntry.MaximumHeartRatePerMinute - lastAthleteEntry.RestingHeartRatePerMinute;
                                double reserveLowValue = Math.Max(0, zone.Low - lastAthleteEntry.RestingHeartRatePerMinute);
                                double reserveHighValue = Math.Max(0, zone.High - lastAthleteEntry.RestingHeartRatePerMinute);

                                if (reserveAmount > 0)
                                {
                                    lower = (reserveLowValue / reserveAmount) * 100;
                                    upper = (reserveHighValue / reserveAmount) * 100;
                                }
                            }
                            else
                            {
                                Debug.Assert(false);
                            }

                            AxisStripe newStripe = new AxisStripe(lower, upper, Color.FromArgb(16, 0, 0, 0));
                            newStripe.Name = zone.Name;
                            result.Add(newStripe);
                        }
                    }
                }
            }

            return result;
        }

        public event PropertyChangedEventHandler DataTrackChanged;

#endregion

        private IActivity m_Activity = null;
        private ActivityDataChangedHelper m_ActivityDataChangedHelper = new ActivityDataChangedHelper(null);
    }
}
